#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"
#include <memory>
#include <signal.h>
 
using namespace ns_tcpserver;
using namespace ns_protocol;
 
// 输出程序使用说明的辅助函数
static void Usage(const std::string &process)
{
    std::cout << "\nUsage: " << process << " port\n"
              << std::endl;
}
 
// 计算器助手函数，根据请求中的运算符和操作数执行相应计算，并返回响应
static Response calculatorHelper(const Request &req)
{
    Response resp(0, 0, req.x_, req.y_, req.op_);
    switch (req.op_)
    {
    case '+': // 加法
        resp.result_ = req.x_ + req.y_;
        break;
    case '-': // 减法
        resp.result_ = req.x_ - req.y_;
        break;
    case '*': // 乘法
        resp.result_ = req.x_ * req.y_;
        break;
    case '/': // 除法
        if (0 == req.y_) // 防止除数为零
            resp.code_ = 1; // 设置错误代码
        else
            resp.result_ = req.x_ / req.y_;
        break;
    case '%': // 取模
        if (0 == req.y_) // 防止除数为零
            resp.code_ = 2; // 设置错误代码
        else
            resp.result_ = req.x_ % req.y_;
        break;
    default: // 无效运算符
        resp.code_ = 3;
        break;
    }
    return resp;
}
 
// 处理客户端连接的函数，接收请求、执行计算并返回结果
void calculator(int sock)
{
    std::string inbuffer;
    while (true)
    {
        // 1. 从套接字读取数据，成功则表示接收到一个请求
        bool res = Recv(sock, &inbuffer);
        if (!res)
            break;
 
        // 2. 解码数据，确保得到一个完整的请求报文
        std::string package = Decode(inbuffer);
        if (package.empty())
            continue;
 
        // 3. 反序列化报文，将字节流转换为结构化的Request对象
        Request req;
        req.Deserialized(package);
 
        // 4. 调用计算器助手函数执行计算，生成Response对象
        Response resp = calculatorHelper(req);
 
        // 5. 序列化计算结果，将其转换为字符串形式
        std::string respString = resp.Serialize();
 
        // 6. 添加长度信息，形成完整响应报文
        respString = Encode(respString);
 
        // 7. 将响应报文发送回客户端
        Send(sock, respString);
    }
}
 
// 注释：已注释掉的信号处理函数
 
// 主函数，接收命令行参数并启动服务器
int main(int argc, char *argv[])
{
    if (argc != 2) // 检查参数数量
    {
        Usage(argv[0]); // 参数不正确时输出使用说明
        exit(1); // 退出程序
    }
 
    // 启动守护进程模式
    MyDaemon();
 
    // 创建并初始化TCP服务器，监听指定端口
    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
 
    // 绑定计算器处理函数到服务器，用于处理客户端连接
    server->BindService(calculator);
 
    // 启动服务器，开始监听和处理客户端连接
    server->Start();
 
    // 注释：已注释掉的测试代码
 
    return 0; // 程序正常结束
}